/**
 * 版权所有(C)，上海勾芒信息科技，2017，所有权利保留。
 * 
 * 项目名：	cards-web
 * 文件名：	RsWxAppUserServiceImpl.java
 * 模块说明：	
 * 修改历史：
 * 2017年4月13日 - Debenson - 创建。
 */
package com.alex.insistence.rest.user.impl;

import java.util.Date;

import org.jeecgframework.core.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alex.insistence.rest.common.MyExceptionCode;
import com.alex.insistence.rest.user.EncryptedUserInfo;
import com.alex.insistence.rest.user.RsAppUser;
import com.alex.insistence.rest.user.RsLoginRequest;
import com.alex.insistence.rest.user.RsLoginResult;
import com.alex.insistence.rest.user.RsMember;
import com.alex.insistence.rest.user.RsUserService;
import com.alex.insistence.rest.util.WxExceptionUtil;
import com.alex.insistence.web.cgform.member.entity.MemberEntity;
import com.alex.insistence.web.cgform.member.entity.MemberGrade;
import com.alex.insistence.web.cgform.member.entity.MemberState;
import com.alex.insistence.web.cgform.member.service.MemberServiceI;
import com.alex.insistence.web.util.EmojiUtil;
import com.alex.wechat.app.account.entity.WxAppAccountEntity;
import com.alex.wechat.app.config.ThirdSessionCache;
import com.alex.wechat.app.config.ThirdSessionCache.ThirdSession;
import com.alex.wechat.app.config.WxAppContext;
import com.gomore.jeecg.common.Assert;
import com.gomore.jeecg.common.ServiceException;

import cn.binarywang.wx.miniapp.api.WxMaServiceEx;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.component.api.WxCompService;

/**
 * 小程序用户相关服务实现。
 * 
 * @author Debenson
 * @since 0.1
 */
@Service("RsUserServiceImpl")
public class RsUserServiceImpl implements RsUserService {
  private static final Logger logger = LoggerFactory.getLogger(RsUserServiceImpl.class);

  @Autowired
  private WxMaServiceEx wxAppService;
  @Autowired
  private WxCompService wxCompService;
  @Autowired
  private MemberServiceI mbrService;

  @Override
  public RsLoginResult login(RsLoginRequest request) throws ServiceException {
    Assert.assertArgumentNotNull(request, "request");
    Assert.assertArgumentNotEmpty(request.getAppId(), "appId");
    Assert.assertArgumentNotEmpty(request.getCode(), "code");

    // 要首先初始化小程序账户
    WxAppContext.setAppId(request.getAppId());
    WxAppAccountEntity account = WxAppContext.getAppAccount();
    if (account == null) {
      throw new ServiceException(MyExceptionCode.notSetWeAppAccount);
    }

    try {
      // 取得微信session key
      WxMaJscode2SessionResult sk = null;
      // if
      // (DeploymentMethod.THIRD_PALTFORM.equals(account.getDeploymentMethod()))
      // {
      // // 如果通过第三方授权，则需要取得第三方账户信息
      // String compAppId = account.getComponentAppId();
      // Assert.assertArgumentNotEmpty(compAppId, "compAppId");
      // WxComponentContext.setAppId(compAppId);
      // sk = wxCompService.getSessionInfo(request.getCode(),
      // request.getAppId());
      //
      // } else {
      // sk = wxAppService.getUserServiceEx().getSessionInfo(request.getCode());
      // }

      sk = wxAppService.getUserServiceEx().getSessionInfo(request.getCode());

      // 解密用户信息
      RsAppUser userInfo = null;
      if (request.getEncryptedUserInfo() != null) {
        WxMaUserInfo maUserInfo = wxAppService.getUserServiceEx().getUserInfo(sk.getSessionKey(),
            request.getEncryptedUserInfo().getEncryptedData(),
            request.getEncryptedUserInfo().getIv());
        userInfo = RsAppUser.copyFrom(maUserInfo);
      }

      // 记录会员登录信息
      try {
        mbrLogin(userInfo, request.getAppId());
      } catch (Exception e) {
        logger.error("记录会员信息失败", e);
      }

      // 创建第三方session
      ThirdSession session = ThirdSessionCache.create(request.getAppId(), sk.getOpenid(), userInfo,
          sk.getSessionKey(), sk.getExpiresin() != null ? sk.getExpiresin().intValue() : 86400);

      RsLoginResult lr = new RsLoginResult();
      lr.setParterId(account.getParterId());
      lr.setParterName(account.getParterName());
      lr.setParterLogoUrl(account.getParterLogoUrl());
      lr.setThirdSessionKey(session.getThirdSessionKey());
      lr.setUserInfo(userInfo);
      if (StringUtil.isEmpty(account.getSelfCanAcquireGiftcard())
          || "Y".equals(account.getSelfCanAcquireGiftcard())) {
        lr.setSelfCanAcquireGiftcard(true);
      } else {
        lr.setSelfCanAcquireGiftcard(false);
      }
      return lr;
    } catch (WxErrorException e) {
      if (e.getError().getErrorCode() == 40163) {
        throw new ServiceException(MyExceptionCode.loginCodeHasUsed);
      }
      throw WxExceptionUtil.build(e);
    }
  }

  /**
   * 记录会员登录信息
   * 
   * @param maUserInfo
   * @return
   */
  private MemberEntity mbrLogin(RsAppUser maUserInfo, String appId) {
    if (maUserInfo == null) {
      return null;
    }

    MemberEntity mbr = mbrService.getByWxaid(maUserInfo.getOpenId());
    if (mbr == null) {
      mbr = new MemberEntity();
      mbr.setWxaid(maUserInfo.getOpenId());
      mbr.setName(EmojiUtil.filterEmoji(maUserInfo.getNickName(), ""));
      mbr.setWxUnionid(maUserInfo.getUnionId());
      mbr.setImgurl(maUserInfo.getAvatarUrl());
      mbr.setGrade(MemberGrade.GRADE_1);
      mbr.setStatus(MemberState.NORMAL);
      mbr.setCreateDate(new Date());
    }
    mbr.setAppId(appId);
    mbr.setMemberId(maUserInfo.getMemberId());
    mbr.setWxUnionid(maUserInfo.getUnionId());
    mbr.setUpdateDate(new Date());
    mbr.setLstLoginTime(new Date());
    mbrService.saveOrUpdate(mbr);
    return mbr;
  }

  @Override
  public RsAppUser decryptUserInfo(EncryptedUserInfo request) throws ServiceException {
    Assert.assertArgumentNotNull(request, "request");

    ThirdSession session = WxAppContext.getThirdSession();
    WxMaUserInfo maUserInfo = wxAppService.getUserServiceEx().getUserInfo(session.getWxSessionKey(),
        request.getEncryptedData(), request.getIv());
    return RsAppUser.copyFrom(maUserInfo);
  }

  @Override
  public RsMember getMemberInfo(String memberCode) throws ServiceException {
    Assert.assertArgumentNotEmpty(memberCode, "memberCode");
    MemberEntity entity = mbrService.getByWxUnionid(memberCode);
    if (entity == null) {
      entity = mbrService.getByWxaid(memberCode);
    }
    if (entity == null) {
      entity = mbrService.getByMbrId(memberCode);
    }
    if (entity == null) {
      throw new ServiceException("指定会员:" + memberCode + "不存在");
    }

    RsMember mbr = new RsMember();
    mbr.setAvatarUrl(entity.getImgurl());
    mbr.setNickName(entity.getName());
    mbr.setOpenId(entity.getWxaid());
    mbr.setUnionId(entity.getWxUnionid());
    return mbr;
  }

}
